home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / Dots & Pixels / sources / flowsettings.cp < prev    next >
Text File  |  1995-09-29  |  9KB  |  320 lines

  1.  
  2. #include <assert.h>
  3. #include <math.h>
  4. #include <ctype.h>
  5. #include <string.h>
  6.  
  7. #include <iostream.h>
  8.  
  9. #include "streamutils.h"
  10. #include "flowsettings.h"
  11.  
  12. ostream& operator<<( ostream& destroom, const flowsettings &thesettings)
  13. {
  14.     char possible_semicolon[ 2] = {0, 0};
  15.     
  16.     destroom << '[';
  17.     if( !thesettings.is_translation_free())
  18.     {
  19.         destroom << possible_semicolon
  20.             << "trans = (" << thesettings.translation_x
  21.             << ',' << thesettings.translation_y << ')';
  22.         possible_semicolon[ 0] = ';';
  23.     }
  24.     if( !thesettings.is_expansion_free())
  25.     {
  26.         destroom << possible_semicolon << "exp = " << thesettings.expansion;
  27.         possible_semicolon[ 0] = ';';
  28.     }
  29.     if( !thesettings.is_rotation_free())
  30.     {
  31.         destroom << possible_semicolon << "rot = " << thesettings.rotation;
  32.         possible_semicolon[ 0] = ';';
  33.     }
  34.     if( !thesettings.is_shear_free())
  35.     {
  36.         destroom << possible_semicolon
  37.             << "shear = (" << thesettings.shear_magnitude
  38.             << ',' << thesettings.shear_direction << ')';
  39.         possible_semicolon[ 0] = ';';
  40.     }
  41.     return destroom << ']';
  42. }
  43.  
  44. istream &operator>>( istream &destroom, flowsettings &thesettings)
  45. {
  46.     thesettings.init();        // give non-specified values standard value
  47.  
  48.     char nextletter;
  49.  
  50.     destroom >> nextletter;    // skips whitespace and newlines
  51.  
  52.     int go_on = (nextletter == '[');
  53.     //
  54.     // 950208: also accept capital letters as input, and accept alternate forms:
  55.     //        x/X for horizontal translation
  56.     //        y/Y for vertical translation
  57.     //        m/M for shear magnitude
  58.     //        d/D for shear direction
  59.     // Note: a problem might occur here, since 'd' also could mean divergence
  60.     //
  61.     while( go_on)
  62.     {
  63.         nextletter = skip_spaces( destroom); // don't skip newlines
  64.         
  65.         switch( nextletter)
  66.         {
  67.             case 't':    // trans
  68.             case 'T':
  69.                 skip_till_numberstart( destroom);
  70.                 destroom >> thesettings.translation_x;
  71.                 destroom >> nextletter; assert( nextletter == ',');
  72.                 destroom >> thesettings.translation_y;
  73.                 destroom >> nextletter; assert( nextletter == ')');
  74.                 break;
  75.  
  76.             case 'x':    // horizontal translation (alternate format)
  77.             case 'X':
  78.                 skip_till_numberstart( destroom);
  79.                 destroom >> thesettings.translation_x;
  80.                 break;
  81.                 
  82.             case 'y':    // vertical translation (alternate format)
  83.             case 'Y':
  84.                 skip_till_numberstart( destroom);
  85.                 destroom >> thesettings.translation_y;
  86.                 break;
  87.                 
  88.             case 'e':    // exp
  89.             case 'E':
  90.                 skip_till_numberstart( destroom);
  91.                 destroom >> thesettings.expansion;
  92.                 break;
  93.  
  94.             case 'r':    // rot
  95.             case 'R':
  96.                 skip_till_numberstart( destroom);
  97.                 destroom >> thesettings.rotation;
  98.                 break;
  99.  
  100.             case 's':    // shear
  101.             case 'S':
  102.                 skip_till_numberstart( destroom);
  103.                 destroom >> thesettings.shear_magnitude;
  104.                 destroom >> nextletter; assert( nextletter == ',');
  105.                 destroom >> thesettings.shear_direction;
  106.                 destroom >> nextletter; assert( nextletter == ')');
  107.                 break;
  108.  
  109.             case 'm':    // shear magnitude (alternate format)
  110.             case 'M':
  111.                 skip_till_numberstart( destroom);
  112.                 destroom >> thesettings.shear_magnitude;
  113.                 break;
  114.                 
  115.             case 'd':    // shear direction (alternate format)
  116.             case 'D':
  117.                 skip_till_numberstart( destroom);
  118.                 destroom >> thesettings.shear_direction;
  119.                 break;
  120.                 
  121.             case ';':
  122.                 //
  123.                 // simply skip this one.
  124.                 //
  125.                 break;
  126.  
  127.             case ']':
  128.                 go_on = false;
  129.                 break;
  130.             
  131.             default:
  132.                 destroom.putback( nextletter);
  133.                 (void)destroom.setf( ios::failbit);
  134.                 go_on = false;
  135.                 break;
  136.         }
  137.     }
  138.     return destroom;
  139. }
  140.  
  141. int flowsettings::operator==( const flowsettings &that) const
  142. {
  143.     return
  144.         (translation_x   == that.translation_x) &&
  145.         (translation_y   == that.translation_y) &&
  146.         (expansion       == that.expansion) &&
  147.         (rotation        == that.rotation) &&
  148.         (shear_magnitude == that.shear_magnitude) &&
  149.         (shear_direction == that.shear_direction);
  150. }
  151.  
  152. ostream& operator<<( ostream& destroom, const flowexpsettings &thesettings)
  153. {
  154.     if( thesettings.point_zero == (const flowsettings &)thesettings)
  155.     {
  156.         return destroom << (flowsettings &)thesettings
  157.                                 << '>' << thesettings.point_one;
  158.     } else {
  159.         return destroom << (flowsettings &)thesettings << '>'
  160.                 << thesettings.point_zero << '-' << thesettings.point_one;
  161.     }
  162. }
  163.  
  164. istream &operator>>( istream &destroom, flowexpsettings &thesettings)
  165. {
  166.     destroom >> (flowsettings &)thesettings;
  167.     char nextletter;
  168.     destroom >> nextletter;        // might be a newline
  169.     if( nextletter == '>')
  170.     {
  171.         destroom >> thesettings.point_zero;
  172.         destroom >> nextletter;
  173.         if( nextletter == '-')
  174.         {
  175.             destroom >> thesettings.point_one;
  176.         } else {
  177.             thesettings.point_one  = thesettings.point_zero;
  178.             thesettings.point_zero = (flowsettings &)thesettings;
  179.             destroom.putback( nextletter);
  180.         }
  181.     } else {
  182.         thesettings.point_zero.init();
  183.         thesettings.point_one.init();
  184.         destroom.putback( nextletter);
  185.         (void)destroom.setf( ios::failbit);
  186.     }
  187.     return destroom;
  188. }
  189.  
  190. void flowexpsettings::shorthand_out( ostream &destroom, int force_three) const
  191. {
  192.     //
  193.     // We start by giving the reference flow:
  194.     //
  195.     const char marker[] = "xyermd";    // mnemonic for dx, dy, exp, rot, mag, dir
  196.     
  197.     destroom << marker << '\t'
  198.         << translation_x   << '\t'
  199.         << translation_y   << '\t'
  200.         << expansion       << '\t'
  201.         << rotation        << '\t'
  202.         << shear_magnitude << '\t'
  203.         << shear_direction;
  204.  
  205.     if( (!force_three) && (point_zero == *(const flowsettings *)this))
  206.     {
  207.         #define dump_if_different( fieldName, prefix)                    \
  208.             if( fieldName != point_one.fieldName)                        \
  209.             {                                                            \
  210.                 destroom << prefix << point_one.fieldName;                \
  211.             }
  212.  
  213.         dump_if_different( translation_x  , "\tx\t");
  214.         dump_if_different( translation_y  , "\ty\t");
  215.         dump_if_different( expansion      , "\te\t");
  216.         dump_if_different( rotation       , "\tr\t");
  217.         dump_if_different( shear_magnitude, "\tm\t");
  218.         dump_if_different( shear_direction, "\td\t");
  219.         
  220.         #undef dump_if_different
  221.     } else {
  222.         #define dump_if_different( fieldName, prefix)                    \
  223.             if( (fieldName != point_one.fieldName)                        \
  224.                 || (fieldName != point_zero.fieldName))                    \
  225.             {                                                            \
  226.                 destroom << prefix << point_zero.fieldName                \
  227.                         << '\t' << point_one.fieldName;                    \
  228.             }
  229.  
  230.         dump_if_different( translation_x  , "\tx\t");
  231.         dump_if_different( translation_y  , "\ty\t");
  232.         dump_if_different( expansion      , "\te\t");
  233.         dump_if_different( rotation       , "\tr\t");
  234.         dump_if_different( shear_magnitude, "\tm\t");
  235.         dump_if_different( shear_direction, "\td\t");
  236.         
  237.         #undef dump_if_different
  238.     }
  239.     destroom << '\t' << marker;
  240. }
  241.  
  242. void flowexpsettings::longhand_out( ostream &destroom, int force_three) const
  243. {
  244.     //
  245.     // We start by giving the reference flow:
  246.     //
  247.     const char marker[] = "xyermd";
  248.     
  249.     destroom << marker << '\t'
  250.         << translation_x   << '\t'
  251.         << translation_y   << '\t'
  252.         << expansion       << '\t'
  253.         << rotation        << '\t'
  254.         << shear_magnitude << '\t'
  255.         << shear_direction;
  256.  
  257.     if( (!force_three) && (point_zero == *(const flowsettings *)this))
  258.     {
  259.         #define dump_anyway( fieldName, prefix)                            \
  260.                         destroom << prefix << point_one.fieldName;
  261.  
  262.         dump_anyway( translation_x  , "\tx\t");
  263.         dump_anyway( translation_y  , "\ty\t");
  264.         dump_anyway( expansion      , "\te\t");
  265.         dump_anyway( rotation       , "\tr\t");
  266.         dump_anyway( shear_magnitude, "\tm\t");
  267.         dump_anyway( shear_direction, "\td\t");
  268.         
  269.         #undef dump_anyway
  270.     } else {
  271.         #define dump_anyway( fieldName, prefix)                \
  272.             destroom << prefix << point_zero.fieldName        \
  273.             << '\t' << point_one.fieldName;
  274.  
  275.         dump_anyway( translation_x  , "\tx\t");
  276.         dump_anyway( translation_y  , "\ty\t");
  277.         dump_anyway( expansion      , "\te\t");
  278.         dump_anyway( rotation       , "\tr\t");
  279.         dump_anyway( shear_magnitude, "\tm\t");
  280.         dump_anyway( shear_direction, "\td\t");
  281.         
  282.         #undef dump_anyway    
  283.     }
  284.     destroom << '\t' << marker;
  285. }
  286.  
  287. void flowexpsettings::getvalue( flowsettings *new_value, const double lambda)
  288. {
  289.     //
  290.     // Note: exp and mag are logarithmical quantities
  291.     //
  292.     new_value->translation_x = lin_interpolate(
  293.             point_zero.translation_x, point_one.translation_x, lambda);
  294.  
  295.     new_value->translation_y = lin_interpolate(
  296.             point_zero.translation_y, point_one.translation_y, lambda);
  297.  
  298.     new_value->expansion =
  299.         log_interpolate( point_zero.expansion, point_one.expansion, lambda);
  300.  
  301.     new_value->rotation =
  302.         lin_interpolate( point_zero.rotation, point_one.rotation, lambda);
  303.  
  304.     new_value->shear_magnitude = log_interpolate(
  305.             point_zero.shear_magnitude, point_one.shear_magnitude, lambda);
  306.  
  307.     new_value->shear_direction = lin_interpolate(
  308.             point_zero.shear_direction, point_one.shear_direction, lambda);
  309. }
  310.  
  311. int flowexpsettings::translation_does_change() const
  312. {
  313.     return (dx_does_change() || dy_does_change());
  314. }
  315.  
  316. int flowexpsettings::shear_does_change() const
  317. {
  318.     return (mag_does_change() || dir_does_change());
  319. }
  320.